<#include "license.ftl">
<@license/>
<#assign object = doc.object>
package ${object.@package}.gwt.mvp.util;

import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Widget;
import redora.client.Persistable;
import redora.client.mvp.ClientFactory;
import redora.client.ui.LazyAnchor;
import redora.client.ui.ListDropdown;
import redora.client.ui.ListPopup;
import redora.client.util.ClientUtil;
import redora.client.util.ClientUtilBase;
import redora.client.util.Field;

import ${object.@package}.gwt.model.*;
import ${object.@package}.gwt.model.fields.${object.@name}Fields;
<#if doc["//enum[@scope='global']"][0]??>
import ${object.@package}.gwt.model.enums.*;
</#if>

import java.util.logging.Logger;
import java.util.ArrayList;
import java.util.Date;

import static java.util.logging.Level.FINE;
import static java.util.logging.Level.SEVERE;
import static redora.client.util.GWTViewUtil.getWidgetById;
import static redora.client.util.GWTViewUtil.NotNull;

public class ${object.@name}Util extends ClientUtilBase<${object.@name}> {
    static Logger l = Logger.getLogger("${object.@name}Util");

    final ClientFactory clientFactory;

    public ${object.@name}Util(final ClientFactory clientFactory) {
        this.clientFactory = clientFactory;
    }

    /**
     * Copies given ${object.@name} to the form panel. Make sure the given fields are available
     * on the panel. If the ${object.@name} is omitted, a new ${object.@name} will be created so the form
     * will be set to the correct default values.
     * @param fojo (Optional) The data
     * @param panel (Mandatory) The form panel
     * @param fields (Mandatory) The fields that are decorated on the panel.
     */
    @Override
    public void copy(final ${object.@name} fojo, final HasWidgets panel, ArrayList<Field> fields) {
        ${object.@name} pojo = fojo;
        if (pojo == null) {
            pojo = new ${object.@name}(Persistable.Scope.Form);
        }
        for (Field field : fields) {
            if (field.name.equals(${object.@name}Fields.id.name)) {
                if (pojo.getId() != null)
                    ((HasValue<String>)getWidgetById(${object.@name}Fields.id, panel)).setValue(pojo.getId().toString());
                else
                    ((HasValue<Date>)getWidgetById(${object.@name}Fields.id, panel)).setValue(null);
            } else if (field.name.equals(${object.@name}Fields.creationDate.name)) {
                ((HasValue<Date>)getWidgetById(${object.@name}Fields.creationDate, panel)).setValue(pojo.getCreationDate());
            } else if (field.name.equals(${object.@name}Fields.updateDate.name)) {
                ((HasValue<Date>)getWidgetById(${object.@name}Fields.updateDate, panel)).setValue(pojo.getUpdateDate());
<#list object.formScope?children as att>
    <#if att?node_type == "element" && att?node_name != "object">
            } else if (field.name.equals(${object.@name}Fields.${att.@fieldName}.name)) {
        <#if att?node_name == "long" || att?node_name == "integer" || att?node_name == "double">
                if (pojo.get${att.@fieldName?cap_first}() != null) {
                    ((HasValue<String>)getWidgetById(${object.@name}Fields.${att.@fieldName}, panel)).setValue(pojo.get${att.@fieldName?cap_first}().toString());
                } else {
                    ((HasValue<String>)getWidgetById(${object.@name}Fields.${att.@fieldName}, panel)).setValue(null);
                }
            <#if att.@parentClass[0]?? && att.@notnull == "true">
                if (!pojo.isNew) {
                    Widget widget = getWidgetById(${object.@name}Fields.${att.@fieldName}, panel);
                    if (widget instanceof ListDropdown)
                        ((ListDropdown)getWidgetById(${object.@name}Fields.${att.@fieldName}, panel)).setMandatory();
                }
            </#if>
        <#elseif att?node_name == "boolean">
                if (pojo.get${att.@fieldName?cap_first}() != null) {
                    ((HasValue<Boolean>)getWidgetById(${object.@name}Fields.${att.@fieldName}, panel)).setValue(pojo.get${att.@fieldName?cap_first}());
                } else
                    ((HasValue<Boolean>)getWidgetById(${object.@name}Fields.${att.@fieldName}, panel)).setValue(null);
        <#elseif att?node_name == "enum">
                if (pojo.get${att.@fieldName?cap_first}() != null) {
                    ((HasValue<String>)getWidgetById(${object.@name}Fields.${att.@fieldName}, panel)).setValue(pojo.get${att.@fieldName?cap_first}().name());
                } else
                    ((HasValue<String>)getWidgetById(${object.@name}Fields.${att.@fieldName}, panel)).setValue(null);
        <#elseif att?node_name == "date" || att?node_name == "datetime">
                if (pojo.get${att.@fieldName?cap_first}() != null) {
                    ((HasValue<Date>)getWidgetById(${object.@name}Fields.${att.@fieldName}, panel)).setValue(pojo.get${att.@fieldName?cap_first}()); //todo
                } else
                    ((HasValue<Date>)getWidgetById(${object.@name}Fields.${att.@fieldName}, panel)).setValue(null);
        <#else>
                if (pojo.get${att.@fieldName?cap_first}() != null) {
                    ((HasValue<String>)getWidgetById(${object.@name}Fields.${att.@fieldName}, panel)).setValue(pojo.get${att.@fieldName?cap_first}());
                } else
                    ((HasValue<String>)getWidgetById(${object.@name}Fields.${att.@fieldName}, panel)).setValue(null);
        </#if>
    </#if>
</#list>
            } else {
                l.log(SEVERE, "Unknown field " + field.name);
            }
        }
    }

    /**
     * Copies from JSON to ${object.@name}.
     * Be sure you have initialized ${object.@name} before running the copy. When you copy an existing ${object.@name},
     * retrieve the last version from the database. In this way it will be known which attributes have been changed.
     */
    @Override
    public ${object.@name} from(JSONObject obj) {
        ${object.@name} retVal = new ${object.@name}(scope(obj));

        retVal.setId(Long.valueOf(obj.get(${object.@name}Fields.id.name).toString()));
        if (obj.containsKey(${object.@name}Fields.creationDate.name) && NotNull(obj.get(${object.@name}Fields.creationDate.name)))
            retVal.creationDate = DATETIME.parse(obj.get(${object.@name}Fields.creationDate.name).isString().stringValue());
        if (obj.containsKey(${object.@name}Fields.updateDate.name) && NotNull(obj.get(${object.@name}Fields.updateDate.name)))
            retVal.updateDate = DATETIME.parse(obj.get(${object.@name}Fields.updateDate.name).isString().stringValue());
<#list object.formScope?children as att>
    <#if att?node_type == "element" && att?node_name != "object">
        if (obj.containsKey(${object.@name}Fields.${att.@fieldName}.name)) {
            if (NotNull(obj.get(${object.@name}Fields.${att.@fieldName}.name))) {
        <#if att?node_name == "long" || att?node_name == "integer" || att?node_name == "double" || att?node_name == "boolean">
                retVal.set${att.@fieldName?cap_first}(${att?node_name?cap_first}.valueOf(obj.get(${object.@name}Fields.${att.@fieldName}.name).toString()));
        <#elseif att?node_name == "enum">
                retVal.set${att.@fieldName?cap_first}(<#if att.@scope == "local">${object.@name}.</#if>${att.@class}.valueOfNullSafe(obj.get(${object.@name}Fields.${att.@fieldName}.name).isString().stringValue()));
        <#elseif att?node_name == "date" || att?node_name == "datetime">
                retVal.set${att.@fieldName?cap_first}(${att?node_name?upper_case}.parse(obj.get(${object.@name}Fields.${att.@fieldName}.name).isString().stringValue()));
        <#else>
                retVal.set${att.@fieldName?cap_first}(obj.get(${object.@name}Fields.${att.@fieldName}.name).isString().stringValue());
        </#if>
            } else {
                retVal.set${att.@fieldName?cap_first}(null);
            }
        }
    </#if>
</#list>
        retVal.dirty.clear();

        return retVal;
    }

    @Override
    public void copy(final HasWidgets panel, final ${object.@name} pojo, ArrayList<Field> fields) {
        for (Field field : fields) {
            if (field.name.equals(${object.@name}Fields.creationDate.name) || field.name.equals(${object.@name}Fields.updateDate.name)) {
                l.log(FINE, "Ignore to persist fields set by the server " + field.name);
            } else if (field.name.equals(${object.@name}Fields.id.name)) {
                if (!isNull((HasValue)getWidgetById(${object.@name}Fields.id, panel))) {
                    pojo.setId(Long.valueOf(((HasValue<String>)getWidgetById(${object.@name}Fields.id, panel)).getValue()));
                    pojo.isNew = false;
                }
<#list object.formScope?children as att>
    <#if att?node_type == "element" && att?node_name != "object">
            } else if (field.name.equals(${object.@name}Fields.${att.@fieldName}.name)) {
        <#if att?node_name == "long" || att?node_name == "integer" || att?node_name == "double">
                pojo.set${att.@fieldName?cap_first}(isNull((HasValue)getWidgetById(${object.@name}Fields.${att.@fieldName}, panel)) ? null
                        : ${att?node_name?cap_first}.valueOf(((HasValue<String>)getWidgetById(${object.@name}Fields.${att.@fieldName}, panel)).getValue()));
        <#elseif att?node_name == "boolean">
                pojo.set${att.@fieldName?cap_first}(isNull((HasValue)getWidgetById(${object.@name}Fields.${att.@fieldName}, panel)) ? null
                        :((HasValue<Boolean>)getWidgetById(${object.@name}Fields.${att.@fieldName}, panel)).getValue());
        <#elseif att?node_name == "enum">
                pojo.set${att.@fieldName?cap_first}(<#if att.@scope == "local">${object.@name}.</#if>${att.@class}.valueOfNullSafe(((HasValue<String>)getWidgetById(${object.@name}Fields.${att.@fieldName}, panel)).getValue()));
        <#elseif att?node_name == "date" || att?node_name == "datetime">
             ; //TODO create
        <#else>
                pojo.set${att.@fieldName?cap_first}(isNull((HasValue)getWidgetById(${object.@name}Fields.${att.@fieldName}, panel)) ? null
                        : ((HasValue<String>)getWidgetById(${object.@name}Fields.${att.@fieldName}, panel)).getValue());
        </#if>
    </#if>
</#list>
            } else {
                l.log(SEVERE, "Unable to persist field: " + field.name);
            }
        }
    }

    @Override
    public String[] from(${object.@name} pojo, Field[] fields) {
        String[] retVal = new String[fields.length];

        for (int i = 0; i < fields.length; i++) {
            if (fields[i].name.equals(${object.@name}Fields.creationDate.name)) {
                if (pojo.getCreationDate() != null)
                    retVal[i] = ClientUtil.DATETIME.format(pojo.getCreationDate());
            } else if (fields[i].name.equals(${object.@name}Fields.updateDate.name)) {
                if (pojo.getUpdateDate() != null)
                    retVal[i] = ClientUtil.DATETIME.format(pojo.getUpdateDate());
            } else if (fields[i].name.equals(${object.@name}Fields.id.name)) {
                if (pojo.getId() != null)
                    retVal[i] = pojo.getId().toString();
<#list object.formScope?children as att>
    <#if att?node_type == "element" && att?node_name != "object">
            } else if (fields[i].name.equals(${object.@name}Fields.${att.@fieldName}.name)) {
        <#if att?node_name == "long" || att?node_name == "integer" || att?node_name == "double" || att?node_name == "boolean">
                if (pojo.get${att.@fieldName?cap_first}() != null)
                    retVal[i] = pojo.get${att.@fieldName?cap_first}().toString();
        <#elseif att?node_name == "enum">
                if (pojo.get${att.@fieldName?cap_first}() != null)
                    retVal[i] = pojo.get${att.@fieldName?cap_first}().name();
        <#elseif att?node_name == "date" || att?node_name == "datetime">
                if (pojo.get${att.@fieldName?cap_first}() != null)
                    retVal[i] = ClientUtil.${att?node_name?upper_case}.format(pojo.get${att.@fieldName?cap_first}());
        <#else>
                retVal[i] = pojo.get${att.@fieldName?cap_first}();
        </#if>
    </#if>
</#list>
            }
        }
        return retVal;
    }
}